#include <string>
#include <set>
#include <fstream>
#include <sstream>
// #include <time.h>
#include "UTH.h"

using namespace phnq::uth;
using namespace std;


UTHValue* testCallback(const void* userData, UTHArray* args)
{
	cout << "test callback!" << endl;
	return new UTHString("yabba dabba doo!!!");
}

void testPerf(char *jsFile)
{	
	ifstream is;
	stringbuf sb;
	char buff[129];
	int length;
		
	is.open (jsFile, ios::in);

	do
	{
		length = is.readsome(buff, 128);
		sb.sputn(buff, length);
	}
	while(length);
	
	is.close();
	
	UTHScript *script = UTHScript::New(sb.str().c_str());
	
	script->compile();

	clock_t c1 = clock();
	UTHValue *result = script->execute();
	clock_t c2 = clock();

	clock_t ticks = c2-c1;
	double t = 1000.0 * (double)ticks / (double)CLOCKS_PER_SEC;

	cout << result->toString() << "\n";
	printf("ms: %f\n", t);

	result->release();
}

int testFunc()
{
	cout << "================================\n";

	
	// char* code = "(function(){return {foo:'bubba', bar:'gump', obby:{obbykid1:'kakak',obbykid2:'ratata'}};})();";
	// char* code = "(function(){var x='yaya'; var y='kaka'; try{ha=42;}catch(ex){return 'nope: '+ex;} return 'hello'+x+y;})();";
	//char* code = "(function(){return {arr: ['foo','bar', 55], num:42, glob:'globby'}.arr[2];})();";
	// const char* code = "({arr: ['foo','barry white', bubba, bubbas[1]], num:42, test:testFn(1, bubba, 3)}.test)";
	//char* code = "(function(){return {arr: ['foo','bar'], num:42, glob:globby, fn:function(){}};})();";
	
	// char* code = "(function(){if(typeof(i)=='undefined')i=0; return i++;})();";
	
	//char* code = "{arr:[1, 'two', 42], foo:'bar', b:bubbas, b2:bubba, fn:testFn(1,2,3)}";
	const char* code = "(function(){return {foo:testFn()};})();";
	
	
	for(int i=0; i<1; i++)
	{
		// char *code = "function(){return 'hi';}()";
		// char *code = "'hello'";
	
	
		UTHScript *script = UTHScript::New(code);
		UTHObject *globals = new UTHObject();
		globals->set("bubba", new UTHString("gump"));

		UTHArray *bubbas = new UTHArray();
		bubbas->add(new UTHString("Larry"));
		bubbas->add(new UTHString("Curly"));
		bubbas->add(new UTHString("Moe"));
		globals->set("bubbas", bubbas);
	
		UTHFunction *testFn = new UTHFunction(testCallback);
		globals->set("testFn", testFn);
	
	
		script->setGlobals(globals);
		script->compile();
	
		UTHValue *result = script->execute();
	
		cout << result->toString() << endl;
	
		globals->release();
		result->release();
	}	
	
	// stringbuf sb2;
	// UTHObject *obj = new UTHObject();
	// 
	// UTHString *str = new UTHString("hello");
	// UTHString *str2 = new UTHString("hello there");
	// obj->set("foo", str);
	// obj->set("foo", str2);
	// obj->set("foo", str2);
	// obj->set("foo", str2);
	// obj->set("foo", str2);
	// str->release();
	// str2->release();
	// 
	// obj->serialize(&sb2);
	// 
	// cout << sb2.str() << "\n";
	
	// obj->release();
}

int main(int argc, char* argv[])
{
	//testPerf(argv[1]);
	
	testFunc();
}